import pygame
import sys
from pygame.locals import *
import time
import pymunk as pm
import math
import os

current_path = os.getcwd()
from characters import Bird
from level import Level
from utils import show_text, to_pygame, vector, unit_vector, distance, is_rect
from game_ui import loading, menu, draw_level_cleared, draw_level_failed





# loading和menu函数已从game_ui模块导入


pygame.init()
# 界面一：loading
loading()
# 界面二：准备游戏界面
menu()
# 界面三：游戏界面
screen = pygame.display.set_mode((1200, 650))
redbird = pygame.image.load(
    os.path.join("images", "red-bird3.png")).convert_alpha()
background2 = pygame.image.load(
    os.path.join("images", "background3.png")).convert_alpha()
sling_image = pygame.image.load(
    os.path.join("images", "sling-3.png")).convert_alpha()
full_sprite = pygame.image.load(
    os.path.join("images", "full-sprite.png")).convert_alpha()
# 扣完全猪
rect = pygame.Rect(181, 1050, 50, 50)
cropped = full_sprite.subsurface(rect).copy()
pig_image = pygame.transform.scale(cropped, (30, 30))
# 按钮
buttons = pygame.image.load(
    os.path.join("images", "selected-buttons.png")).convert_alpha()
# 失败->猪
pig_happy = pygame.image.load(
    os.path.join("images", "pig_failed.png")).convert_alpha()
# 三星
stars = pygame.image.load(
    os.path.join("images", "stars-edited.png")).convert_alpha()
rect = pygame.Rect(0, 0, 200, 200)
star1 = stars.subsurface(rect).copy()
rect = pygame.Rect(204, 0, 200, 200)
star2 = stars.subsurface(rect).copy()
rect = pygame.Rect(426, 0, 200, 200)
star3 = stars.subsurface(rect).copy()
# 暂停（小）
rect = pygame.Rect(164, 10, 60, 60)
pause_button = buttons.subsurface(rect).copy()
# 重玩
rect = pygame.Rect(24, 4, 100, 100)
replay_button = buttons.subsurface(rect).copy()
# 下一关
rect = pygame.Rect(142, 365, 130, 100)
next_button = buttons.subsurface(rect).copy()
# 开始游戏
rect = pygame.Rect(18, 212, 100, 100)
play_button = buttons.subsurface(rect).copy()

# 游戏计时开始
# 创建时钟对象 (可以控制游戏循环频率)
clock = pygame.time.Clock()
running = True

space = pm.Space()
space.gravity = (0.0, -800.0)   # 重力向量
pigs = []
birds = []
balls = []
polys = []
beams = []
columns = []
poly_points = []
ball_number = 0
polys_dict = {}
mouse_distance = 0
rope_length = 90
angle = 0
x_mouse = 0
y_mouse = 0
count = 0
mouse_pressed = False
t1 = 0
t2 = 0  # 初始化t2变量
tick_to_next_circle = 10
RED = (255, 0, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
sling_x, sling_y = 135, 450
sling2_x, sling2_y = 160, 450
score = 0
game_state = 0
bird_path = []
counter = 0
restart_counter = False
bonus_score_once = True
bold_font = pygame.font.SysFont("arial", 30, bold=True)
bold_font2 = pygame.font.SysFont("arial", 40, bold=True)
bold_font3 = pygame.font.SysFont("arial", 50, bold=True)
wall = False

# 静态实体即固定不动的实体，一般不可被穿过。比如地面和墙。
# Static floor
# 定义静态刚体
static_body = pm.Body(body_type=pm.Body.STATIC)
static_lines = [pm.Segment(static_body, (0.0, 60.0), (1200.0, 60.0), 0.0)]
static_lines1 = [pm.Segment(static_body, (1200.0, 60.0), (1200.0, 800.0), 0.0)]

# 先配置线段属性
for line in static_lines:
    line.elasticity = 0.95
    line.friction = 0.9
    line.collision_type = 3
for line in static_lines1:
    line.elasticity = 0.95
    line.friction = 1
    line.collision_type = 3

# 添加线段时，同时添加其所属的刚体static_body
space.add(static_body)
for line in static_lines:
    space.add(line)
for line in static_lines1:
    space.add(line)


def load_music():
    song1 = os.path.join('music', 'ambient_red_savannah.wav')
    pygame.mixer.music.load(song1)
    pygame.mixer.music.play(-1)


def sling_action():
    """Set up sling behavior"""
    global mouse_distance
    global rope_length
    global angle
    global x_mouse
    global y_mouse
    # 固定鸟在绳索上
    v = vector((sling_x, sling_y), (x_mouse, y_mouse))  # 鼠标到绳索的向量
    uv = unit_vector(v)  # 单位向量
    uv1 = uv[0]
    uv2 = uv[1]
    mouse_distance = distance(sling_x, sling_y, x_mouse, y_mouse)  # 鼠标到绳索的距离
    pu = (uv1 * rope_length + sling_x, uv2 * rope_length + sling_y)  # 最大长度
    bigger_rope = 102  # 绳子的最大长度

    x_redbird = x_mouse - 20  # 鼠标位置是鸟的中心
    y_redbird = y_mouse - 20

    if mouse_distance > rope_length:
        pux, puy = pu
        pux -= 20  # 移到鼠标中心
        puy -= 20
        pul = pux, puy
        screen.blit(redbird, pul)  # 画鸟
        pu2 = (uv1 * bigger_rope + sling_x, uv2 * bigger_rope + sling_y)
        pygame.draw.line(screen, (0, 0, 0), (sling2_x, sling2_y), pu2, 5)  # 画线 弹弓的线
        pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y), pu2, 5)
    else:
        mouse_distance += 10  # 把鸟移到绳子上
        screen.blit(redbird, (x_redbird, y_redbird))
        pu3 = (uv1 * mouse_distance + sling_x, uv2 * mouse_distance + sling_y)
        pygame.draw.line(screen, (0, 0, 0), (sling2_x, sling2_y), pu3, 5)
        pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y), pu3, 5)
    # 计算角度 鸟到弹弓中心
    dy = y_mouse - sling_y
    dx = x_mouse - sling_x
    if dx == 0:
        dx = 0.00000000000001
    angle = math.atan((float(dy)) / dx)


# draw_level_cleared和draw_level_failed函数已从game_ui模块导入


def restart():
    """Delete all objects of the level"""
    pigs_to_remove = []
    birds_to_remove = []
    columns_to_remove = []
    beams_to_remove = []
    for pig in pigs:
        pigs_to_remove.append(pig)
    for pig in pigs_to_remove:
        space.remove(pig.shape)
        space.remove(pig.body)
        pigs.remove(pig)
    for bird in birds:
        birds_to_remove.append(bird)
    for bird in birds_to_remove:
        space.remove(bird.shape)
        space.remove(bird.body)
        birds.remove(bird)
    for column in columns:
        columns_to_remove.append(column)
    for column in columns_to_remove:
        space.remove(column.shape)
        space.remove(column.body)
        columns.remove(column)
    for beam in beams:
        beams_to_remove.append(beam)
    for beam in beams_to_remove:
        space.remove(beam.shape)
        space.remove(beam.body)
        beams.remove(beam)


def post_solve_bird_pig(arbiter, space, _):
    """Collision between bird and pig"""
    surface = screen
    a, b = arbiter.shapes
    bird_body = a.body
    pig_body = b.body
    p = to_pygame(bird_body.position)
    p2 = to_pygame(pig_body.position)
    r = 30
    pygame.draw.circle(surface, BLACK, p, r, 4)
    pygame.draw.circle(surface, RED, p2, r, 4)
    pigs_to_remove = []
    for pig in pigs:
        if pig_body == pig.body:
            pig.life -= 20
            pigs_to_remove.append(pig)
            global score
            score += 10000
    for pig in pigs_to_remove:
        space.remove(pig.shape)
        space.remove(pig.body)
        pigs.remove(pig)


def post_solve_bird_wood(arbiter, space, _):
    """Collision between bird and wood"""
    poly_to_remove = []
    if arbiter.total_impulse.length > 1100:
        a, b = arbiter.shapes
        for column in columns:
            if b == column.shape:
                poly_to_remove.append(column)
        for beam in beams:
            if b == beam.shape:
                poly_to_remove.append(beam)
        for poly in poly_to_remove:
            if poly in columns:
                columns.remove(poly)
            if poly in beams:
                beams.remove(poly)
            space.remove(poly.shape)
            space.remove(poly.body)
        global score
        score += 5000


def post_solve_pig_wood(arbiter, space, _):
    """Collision between pig and wood"""
    pigs_to_remove = []
    if arbiter.total_impulse.length > 700:
        pig_shape, wood_shape = arbiter.shapes
        for pig in pigs:
            if pig_shape == pig.shape:
                pig.life -= 20
                global score
                score += 10000
                if pig.life <= 0:
                    pigs_to_remove.append(pig)
    for pig in pigs_to_remove:
        space.remove(pig.shape)
        space.remove(pig.body)
        pigs.remove(pig)

# 注意：通过 space 实例创建碰撞处理器，使用on_collision方法
# bird and pigs
space.on_collision(0, 1, None, None, post_solve_bird_pig, None, None)
# bird and wood
space.on_collision(0, 2, None, None, post_solve_bird_wood, None, None)
# pig and wood
space.on_collision(1, 2, None, None, post_solve_pig_wood, None, None)

load_music()
level = Level(pigs, columns, beams, space)
level.number = 0
level.load_level()
while running:
    # Input handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
        # 判断使用小鸟
        if (pygame.mouse.get_pressed()[0] and
                100 < x_mouse < 250 and 370 < y_mouse < 550):
            music_flag = 0
            if not mouse_pressed:
                music_flag = 1

            mouse_pressed = True

            music_flag += 1
            if music_flag == 2:
                song_rope = os.path.join('music', 'slingshot streched.wav')
                pygame.mixer.music.load(song_rope)
                pygame.mixer.music.play(0)

        if (event.type == pygame.MOUSEBUTTONUP and
                event.button == 1 and mouse_pressed):
            # Release new bird
            mouse_pressed = False
            if level.number_of_birds > 0:
                song_fly = os.path.join('music', 'bird 01 flying.wav')
                pygame.mixer.music.load(song_fly)
                pygame.mixer.music.play(0)

                level.number_of_birds -= 1
                t1 = time.time() * 1000
                xo = 154
                yo = 156
                if mouse_distance > rope_length:
                    mouse_distance = rope_length
                if x_mouse < sling_x + 5:
                    bird = Bird(mouse_distance, angle, xo, yo, space)
                    birds.append(bird)
                else:
                    bird = Bird(-mouse_distance, angle, xo, yo, space)
                    birds.append(bird)
                if level.number_of_birds == 0:
                    t2 = time.time()
        if event.type == pygame.MOUSEBUTTONUP and event.button == 1:  # 菜单栏
            if x_mouse < 60 and 90 < y_mouse < 155:
                game_state = 1
            if game_state == 1:
                if x_mouse > 500 and 200 < y_mouse < 300:
                    # Resume in the paused screen
                    game_state = 0
                if x_mouse > 500 and y_mouse > 300:
                    # Restart in the paused screen
                    restart()
                    level.load_level()
                    game_state = 0
                    bird_path = []
            if game_state == 3:
                # Restart in the failed level screen
                if 500 < x_mouse < 620 and y_mouse > 450:
                    restart()
                    level.load_level()
                    game_state = 0
                    bird_path = []
                    score = 0
            if game_state == 4:
                # Build next level
                if x_mouse > 610 and y_mouse > 450:
                    restart()
                    level.number += 1
                    game_state = 0
                    level.load_level()
                    score = 0
                    bird_path = []
                    bonus_score_once = True
                if 500 < x_mouse < 610 and y_mouse > 450:
                    # Restart in the level cleared screen
                    restart()
                    level.load_level()
                    game_state = 0
                    bird_path = []
                    score = 0
    x_mouse, y_mouse = pygame.mouse.get_pos()
    # Draw background
    screen.fill((130, 200, 100))  # 填充底部的绿色
    screen.blit(background2, (0, -50))
    # Draw first part of the sling
    rect = pygame.Rect(50, 0, 70, 220)
    screen.blit(sling_image, (138, 420), rect)
    # Draw the trail left behind
    for point in bird_path:
        pygame.draw.circle(screen, WHITE, point, 5, 0)
    # Draw the birds in the wait line
    if level.number_of_birds > 0:
        for i in range(level.number_of_birds - 1):
            x = 100 - (i * 35)
            screen.blit(redbird, (x, 508))
    # Draw sling behavior
    if mouse_pressed and level.number_of_birds > 0:
        sling_action()
    else:
        if time.time() * 1000 - t1 > 300 and level.number_of_birds > 0:
            screen.blit(redbird, (130, 426))
        else:
            pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y - 8),
                             (sling2_x, sling2_y - 7), 5)
    birds_to_remove = []
    pigs_to_remove = []
    counter += 1
    # Draw birds
    for bird in birds:
        if bird.shape.body.position.y < 0:
            birds_to_remove.append(bird)
        p = to_pygame(bird.shape.body.position)
        x, y = p
        x -= 22
        y -= 20
        screen.blit(redbird, (x, y))
        pygame.draw.circle(screen, BLUE,
                           p, int(bird.shape.radius), 2)
        if counter >= 3 and time.time() - t1 < 5:
            bird_path.append(p)
            restart_counter = True
    if restart_counter:
        counter = 0
        restart_counter = False
    # Remove birds and pigs
    for bird in birds_to_remove:
        space.remove(bird.shape)
        space.remove(bird.body)
        birds.remove(bird)
    for pig in pigs_to_remove:
        space.remove(pig.shape)
        space.remove(pig.body)
        pigs.remove(pig)
    i = 0
    # Draw pigs
    for pig in pigs:
        i += 1
        pig = pig.shape
        if pig.body.position.y < 0:
            pigs_to_remove.append(pig)

        p = to_pygame(pig.body.position)
        x, y = p

        angle_degrees = math.degrees(pig.body.angle)
        img = pygame.transform.rotate(pig_image, angle_degrees)
        w, h = img.get_size()
        x -= w * 0.5
        y -= h * 0.5
        screen.blit(img, (x, y))
        pygame.draw.circle(screen, BLUE, p, int(pig.radius), 2)
    # Draw columns and Beams
    for column in columns:
        column.draw_poly('columns', screen)
    for beam in beams:
        beam.draw_poly('beams', screen)
    # Update physics
    dt = 1.0 / 50.0 / 2.
    for x in range(2):
        space.step(dt)  # make two updates per frame for better stability
    # Drawing second part of the sling
    rect = pygame.Rect(0, 0, 60, 200)
    screen.blit(sling_image, (120, 420), rect)
    # Draw score
    score_font = bold_font.render("SCORE", 1, WHITE)
    number_font = bold_font.render(str(score), 1, WHITE)
    screen.blit(score_font, (1060, 90))
    if score == 0:
        screen.blit(number_font, (1100, 130))
    else:
        screen.blit(number_font, (1060, 130))
    screen.blit(pause_button, (10, 90))
    # Pause option
    if game_state == 1:
        screen.blit(play_button, (500, 200))
        screen.blit(replay_button, (500, 300))
    
    # 调用draw_level_cleared和draw_level_failed函数，传递所需参数
    game_state, bonus_score_once, score = draw_level_cleared(screen, level, pigs, score, game_state, bonus_score_once, bold_font3, bold_font2, WHITE, BLACK, star1, star2, star3, replay_button, next_button)
    game_state = draw_level_failed(screen, level, pigs, t2, game_state, bold_font3, WHITE, BLACK, pig_happy, replay_button)
    
    pygame.display.flip()
    clock.tick(50)